package com.suredy.app.project.ctrl;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import com.suredy.app.project.constants.DicKey;
import com.suredy.app.project.constants.ProjectStatus;
import com.suredy.app.project.service.ProjectSrv;
import com.suredy.core.ctrl.BaseCtrl;
import com.suredy.core.service.DictionarySrv;
import com.suredy.security.entity.User2RoleEntity;
import com.suredy.security.model.Role;
import com.suredy.security.model.User;
import com.suredy.security.service.RoleSrv;
import com.suredy.security.service.User2RoleSrv;

/**
 * 报表服务
 * 
 * @author VIVID.G
 * @since 2015-9-22
 * @version v0.1
 */
@Controller
@RequestMapping("/reports")
public class ReportsCtrl extends BaseCtrl {

	@Value("${role.proj_manager}")
	private String roleCodeOfProjManager;

	@Autowired
	private DictionarySrv dictionarySrv;

	@Autowired
	private RoleSrv roleSrv;

	@Autowired
	private User2RoleSrv user2RoleSrv;

	@Autowired
	private ProjectSrv projectSrv;

	@RequestMapping(method = RequestMethod.GET)
	public String index(Model model) {
		String view = "app/reports/index";

		model.addAttribute("type", this.projType());
		model.addAttribute("status", this.projStatus());
		model.addAttribute("obtain", this.projObtain());
		model.addAttribute("manager", this.projManager());
		model.addAttribute("customerCompany", this.projCustomerCompany());

		return view;
	}

	@RequestMapping(value = "/data", method = RequestMethod.POST)
	@ResponseBody
	public Object chartData(Integer year, Integer month, ProjectStatus status, String customerCompany, String manager, String type, String obtain) {
		List<Map<String, Object>> data = this.projectSrv.getReportData(year, month, status, customerCompany, manager, type, obtain);

		if (data == null || data.isEmpty())
			return false;

		Map<String, Object> ret = new HashMap<String, Object>();

		Object chartData = this.dataOfAmountChart(data);
		if (chartData != null)
			ret.put("money", chartData);

		chartData = this.dataOfStatusChart(data);
		if (chartData != null)
			ret.put("status", chartData);

		chartData = this.dataOfManagerChart(data);
		if (chartData != null)
			ret.put("manager", chartData);

		chartData = this.dataOfCustomerChart(data);
		if (chartData != null)
			ret.put("customer", chartData);

		return ret.isEmpty() ? false : ret;
	}

	private List<String> projObtain() {
		return this.dictionarySrv.getVals(DicKey.PROJ_OBTAIN);
	}

	private List<String> projType() {
		return this.dictionarySrv.getVals(DicKey.PROJ_TYPE);
	}

	private ProjectStatus[] projStatus() {
		return ProjectStatus.values();
	}

	private List<String> projCustomerCompany() {
		return this.dictionarySrv.getVals(DicKey.CUSTOMER_COMPANY);
	}

	private List<User> projManager() {
		if (StringUtils.isBlank(this.roleCodeOfProjManager))
			return null;

		if (StringUtils.isBlank(this.getUser().getOrgUniqueCode()))
			return null;

		String roleCode = "G=" + this.roleCodeOfProjManager + "/" + this.getUser().getOrgUniqueCode();

		Role role = this.roleSrv.getByCode(roleCode);

		if (role == null || StringUtils.isBlank(role.getId()))
			return null;

		List<User2RoleEntity> data = this.user2RoleSrv.getByRole(role.getId());

		if (data == null || data.isEmpty())
			return null;

		List<User> ret = new ArrayList<User>();

		for (User2RoleEntity entity : data) {
			if (entity.getUser() != null)
				ret.add(entity.getUser().toVO());
		}

		return ret.isEmpty() ? null : ret;
	}

	private Object dataOfAmountChart(List<Map<String, Object>> data) {
		if (data == null || data.isEmpty())
			return null;

		Map<String, List<Object>> ret = new HashMap<String, List<Object>>();
		ret.put("xData", new ArrayList<Object>());
		ret.put("yData", new ArrayList<Object>());

		List<Object> xData = ret.get("xData");
		xData.add("合同金额");
		xData.add("结算金额");
		xData.add("收款金额");
		xData.add("支出金额");

		float price = 0f;
		float payPrice = 0f;
		float payIn = 0f;
		float payOut = 0f;

		for (Map<String, Object> d : data) {
			price += (float) d.get("price");
			payPrice += (float) d.get("payPrice");
			payIn += ((Double) d.get("payIn")).floatValue();
			payOut += ((Double) d.get("payOut")).floatValue();
		}

		List<Object> yData = ret.get("yData");
		yData.add(price);
		yData.add(payPrice);
		yData.add(payIn);
		yData.add(payOut);

		return ret;
	}

	private Object dataOfStatusChart(List<Map<String, Object>> data) {
		if (data == null || data.isEmpty())
			return null;

		Map<String, List<Object>> ret = new HashMap<String, List<Object>>();
		ret.put("xData", new ArrayList<Object>());
		ret.put("yData", new ArrayList<Object>());

		List<Object> xData = ret.get("xData");
		xData.add(ProjectStatus.NOT_START.getVal());
		xData.add(ProjectStatus.STARTED.getVal());
		xData.add(ProjectStatus.COMPLETED.getVal());
		xData.add(ProjectStatus.SUSPEND.getVal());

		int notStart = 0;
		int started = 0;
		int completed = 0;
		int suspend = 0;

		for (Map<String, Object> d : data) {
			switch ((ProjectStatus) d.get("status")) {
				case NOT_START:
					notStart += 1;
					break;
				case STARTED:
					started += 1;
					break;
				case COMPLETED:
					completed += 1;
					break;
				case SUSPEND:
					suspend += 1;
					break;
			}
		}

		List<Object> yData = ret.get("yData");
		yData.add(notStart);
		yData.add(started);
		yData.add(completed);
		yData.add(suspend);

		return ret;
	}

	private Object dataOfManagerChart(List<Map<String, Object>> data) {
		if (data == null || data.isEmpty())
			return null;

		Map<String, Integer> tmp = new LinkedHashMap<String, Integer>();

		for (Map<String, Object> dd : data) {
			String manager = dd.get("manager").toString();

			if (StringUtils.isBlank(manager))
				manager = "未知";

			if (!tmp.containsKey(manager))
				tmp.put(manager, 0);

			tmp.put(manager, tmp.get(manager) + 1);
		}

		// 将 "未知" 放到列表最后
		if (tmp.containsKey("未知")) {
			Integer count = tmp.remove("未知");
			tmp.put("未知", count);
		}

		Map<String, List<?>> ret = new HashMap<String, List<?>>();
		List<String> legend = new ArrayList<String>();
		List<Map<String, Object>> d = new ArrayList<Map<String, Object>>();

		ret.put("legend", legend);
		ret.put("data", d);

		for (Map.Entry<String, Integer> entry : tmp.entrySet()) {
			String manager = entry.getKey();
			Integer count = entry.getValue();

			legend.add(manager);

			Map<String, Object> item = new HashMap<String, Object>();
			item.put("name", manager);
			item.put("value", count);

			d.add(item);
		}

		return ret;
	}

	private Object dataOfCustomerChart(List<Map<String, Object>> data) {
		if (data == null || data.isEmpty())
			return null;

		Map<String, Integer> tmp = new LinkedHashMap<String, Integer>();

		for (Map<String, Object> dd : data) {
			String manager = dd.get("customerCompany").toString();

			if (StringUtils.isBlank(manager))
				manager = "未知";

			if (!tmp.containsKey(manager))
				tmp.put(manager, 0);

			tmp.put(manager, tmp.get(manager) + 1);
		}

		// 将 "未知" 放到列表最后
		if (tmp.containsKey("未知")) {
			Integer count = tmp.remove("未知");
			tmp.put("未知", count);
		}

		Map<String, List<?>> ret = new HashMap<String, List<?>>();
		List<String> legend = new ArrayList<String>();
		List<Map<String, Object>> d = new ArrayList<Map<String, Object>>();

		ret.put("legend", legend);
		ret.put("data", d);

		for (Map.Entry<String, Integer> entry : tmp.entrySet()) {
			String manager = entry.getKey();
			Integer count = entry.getValue();

			legend.add(manager);

			Map<String, Object> item = new HashMap<String, Object>();
			item.put("name", manager);
			item.put("value", count);

			d.add(item);
		}

		return ret;
	}

}
